﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yitter.IdGenerator;
using Admin.NET.Core;

namespace Admin.NET.Application
{
    /// <summary>
    /// 出库管理服务
    /// </summary>
    [ApiDescriptionSettings("自己的业务", Name = "ExWarehouse", Order = 100)]
    [Route("api/[Controller]")]
    public class ExWarehouseService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WmsArea, MasterDbContextLocator> _wmsAreaRep;
        private readonly IRepository<WmsPlace, MasterDbContextLocator> _wmsPlaceRep;
        private readonly IRepository<WmsTask, MasterDbContextLocator> _wmsTaskRep;
        private readonly IRepository<WmsContainer, MasterDbContextLocator> _wmsContainerRep;
        private readonly IRepository<WmsContainerPlace, MasterDbContextLocator> _wmsContainerPlaceRep;
        private readonly IRepository<WmsMaterial, MasterDbContextLocator> _wmsMaterialRep;
        private readonly IRepository<WmsMaterialStock, MasterDbContextLocator> _wmsMaterialStockRep;
        private readonly IRepository<WmsMaterialContainer, MasterDbContextLocator> _wmsMaterialContainerRep;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ExWarehouseService(
                        IRepository<WmsArea, MasterDbContextLocator> wmsAreaRep,
                        IRepository<WmsPlace, MasterDbContextLocator> wmsPlaceRep,
                        IRepository<WmsTask, MasterDbContextLocator> wmsTaskRep,
                        IRepository<WmsContainer, MasterDbContextLocator> wmsContainerRep,
                        IRepository<WmsContainerPlace, MasterDbContextLocator> wmsContainerPlaceRep,
                        IRepository<WmsMaterial, MasterDbContextLocator> wmsMaterialRep,
                        IRepository<WmsMaterialStock, MasterDbContextLocator> wmsMaterialStockRep,
                        IRepository<WmsMaterialContainer, MasterDbContextLocator> wmsMaterialContainerRep
            )
        {
            this._wmsAreaRep = wmsAreaRep;
            this._wmsPlaceRep = wmsPlaceRep;
            this._wmsTaskRep = wmsTaskRep;
            this._wmsContainerRep = wmsContainerRep;
            this._wmsContainerPlaceRep = wmsContainerPlaceRep;
            this._wmsMaterialRep = wmsMaterialRep;
            this._wmsMaterialStockRep = wmsMaterialStockRep;
            this._wmsMaterialContainerRep = wmsMaterialContainerRep;
        }

        


        /// <summary>
        /// 分页查询物料出库管理信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("page")]
        public async Task<PageResult<ExWareHouseOutput>> Page([FromQuery] ExWarehouseSearch input)
        {
            var wmsMaterialStocks = await _wmsMaterialStockRep.DetachedEntities
                      .Where (!string.IsNullOrEmpty(input.MaterialName), u => EF.Functions.Like(u.MaterialName, $"%{input.MaterialName.Trim()}%"))
                      .ProjectToType<ExWareHouseOutput>()
                      .ToListAsync();
            return wmsMaterialStocks.ToADPagedList(input.PageNo, input.PageSize);
        }

        /// <summary>
        /// 自动出库
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        [HttpPost("AutoExWarehouse")]
        [UnitOfWork]
        public async Task AutoExWarehouse(List<ExWarehouseInput> inputs)
        {
            // 根据托盘号、库位编号去重
            var containerCodeDistinct = inputs.Select(u => new { u.ContainerCode, u.PlaceCode }).Distinct().ToList();
            if (containerCodeDistinct.Count <= 0) throw Oops.Oh("暂无库存出库");

            // 查询库区名称
            var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
            if (wmsArea != null) throw Oops.Oh("库区不存在");

            foreach (var item in containerCodeDistinct)
            {
                var wmsMaterialContainerList = new List<WmsMaterialContainer>();
                // 判断任务
                var wmsTask = await _wmsTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == item.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
                if (wmsTask != null) throw Oops.Oh("周转箱号存在未完成的任务!");

                // 检查周转箱号信息
                var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == item.ContainerCode);
                if (wmsContainer == null) throw Oops.Oh("库存中没有该：" + wmsContainer.ContainerCode + "托盘!");

                // 检查库位信息
                var wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(p => p.PlaceCode == item.PlaceCode);
                if (wmsPlace == null) throw Oops.Oh("库位不存在!");
                if (wmsPlace.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");

                // 更新状态为“待出”
                wmsPlace.PlaceStatus = PlaceStatus.DAICHU;
                await _wmsPlaceRep.UpdateAsync(wmsPlace);

                // 检查库存
                var wmsMaterialStockList = inputs.Where(u => u.ContainerCode == wmsContainer.ContainerCode && u.PlaceCode == wmsPlace.PlaceCode).ToList();
                if (wmsMaterialStockList.Count <= 0) throw Oops.Oh("库存数据异常!");

                // 检查库位与周转箱号关系
                var wmsContainerPlace = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.ContainerId == wmsContainer.Id
                && p.PlaceCode == wmsPlace.PlaceCode && p.PlaceId == wmsPlace.Id && p.ContainerPlaceStatus == CommonStatus.ENABLE);
                if (wmsContainerPlace == null) throw Oops.Oh("托盘号与库位关系不存在!");

                // 不是空料箱才会有组盘关系
                if (wmsPlace.EmptyContainer == YesOrNot.N)
                {
                    // 检查物料与周转箱号关系 
                    wmsMaterialContainerList = await _wmsMaterialContainerRep.Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();
                    if (wmsMaterialContainerList.Count <= 0) throw Oops.Oh("周转箱号与物料关系不存在!");
                }
                else
                {
                    // 更新空料箱库存
                    var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsContainer.ContainerCode);
                    if (wmsMaterialStock.Source == RuKuSourceEnum.KONGTUO)
                    {
                        wmsMaterialStock.PlaceCode = "N/A";
                        await _wmsMaterialStockRep.UpdateAsync(wmsMaterialStock);
                    }
                }
                if (wmsTask == null)
                {
                    string taskNo = "CHUKU" + DateTime.Today.ToString("yyyyMMdd");
                    var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
                    if (wmsTaskModel == null)
                    {
                        taskNo = taskNo + "0001";
                    }
                    else
                    {
                        //获取流水号最大的数据
                        var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
                        taskNo = SysCommUtil.GenerateNewInvoiceNumber(maxSerialNumber, 1);
                    }

                    // 新增任务
                    var takmodel = new WmsTask()
                    {
                        TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
                        TaskModel = TaskModel.QUANZIDONG,
                        TaskType = TaskType.CHUKU,
                        TaskLevel = 1,
                        TaskStatus = TaskStatusEnum.WEIZHIXING,
                        ContainerCode = wmsContainer.ContainerCode,
                        SourcePlace = wmsPlace.PlaceCode,
                        Aisle = wmsPlace.Aisle,
                        ToPlace = "出库口",
                        AreaName = wmsArea.AreaName,
                        Description = wmsPlace.EmptyContainer == YesOrNot.Y ? "空托" : "物料",
                        OrderNo = wmsMaterialContainerList.Count <= 0 ? "N/A" : wmsMaterialContainerList.FirstOrDefault().OrderNo,
                        TaskDodeviceStatus = TaskDodeviceStatusEnum.W,
                        IsRead = true
                    };
                    await _wmsTaskRep.InsertAsync(takmodel);
                }
            }
        }

        /// <summary>
        /// 人工出库
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        [HttpPost("manualExWarehouse")]
        [UnitOfWork]
        public async Task ManualExWarehouse(List<ExWarehouseInput> inputs)
        {
            // 根据托盘号、库位编号去重
            var containerCodeDistinct = inputs.Select(u => new { u.ContainerCode, u.PlaceCode }).Distinct().ToList();
            if (containerCodeDistinct.Count <= 0) throw Oops.Oh("暂无库存出库");

            // 查询库区名称
            var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
            if (wmsArea != null) throw Oops.Oh("库区不存在");

            foreach (var item in containerCodeDistinct)
            {
                var wmsMaterialContainerList = new List<WmsMaterialContainer>();
                // 判断任务
                var wmsTask = await _wmsTaskRep.FirstOrDefaultAsync(p => p.ContainerCode == item.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
                if (wmsTask != null) throw Oops.Oh("托盘号存在未完成的任务!");

                // 检查托盘号信息
                var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == item.ContainerCode);
                if (wmsContainer == null) throw Oops.Oh("周转箱号不存在!");

                // 检查库位信息
                var wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(p => p.PlaceCode == item.PlaceCode);
                if (wmsPlace == null) throw Oops.Oh("库位不存在!");
                if (wmsPlace.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");

                // 检查库存
                var wmsMaterialStockList = inputs.Where(u => u.ContainerCode == wmsContainer.ContainerCode && u.PlaceCode == wmsPlace.PlaceCode).ToList();
                if (wmsMaterialStockList.Count <= 0) throw Oops.Oh("库存数据异常!");

                // 检查库位与托盘号关系
                var wmsContainerPlace = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.ContainerId == wmsContainer.Id
                && p.PlaceCode == wmsPlace.PlaceCode && p.PlaceId == wmsPlace.Id && p.ContainerPlaceStatus == CommonStatus.ENABLE);
                if (wmsContainerPlace == null) throw Oops.Oh("托盘号与库位关系不存在!");


                // 不是空托才会有组盘关系
                if (wmsPlace.EmptyContainer == YesOrNot.N)
                {
                    // 检查物料与空托号关系 
                    wmsMaterialContainerList = await _wmsMaterialContainerRep.Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();
                    if (wmsMaterialContainerList.Count <= 0) throw Oops.Oh("托盘号与物料关系不存在!");
                }
                else
                {
                    // 更新空料箱库存
                    var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsContainer.ContainerCode);
                    if (wmsMaterialStock.Source == RuKuSourceEnum.KONGTUO)
                    {
                        await _wmsMaterialStockRep.DeleteAsync(wmsMaterialStock);
                    }
                }

                if (wmsTask == null)
                {
                    //构建出库物料和周转箱号关系
                    var orderNo = "N/A";
                    if (wmsMaterialContainerList.Count > 0) orderNo = YitIdHelper.NextId().ToString();

                    foreach (var wmsMaterialContaine in wmsMaterialContainerList)
                    {
                        //更新状态为”删除“
                        wmsMaterialContaine.BindStatus = CommonStatus.DELETED;
                        await _wmsMaterialContainerRep.UpdateNowAsync(wmsMaterialContaine);

                        //新增组盘绑定记录 正常
                        var addWmsMaterialContainer = wmsMaterialContaine;
                        addWmsMaterialContainer.Id = YitIdHelper.NextId();
                        addWmsMaterialContainer.OrderNo = orderNo;
                        addWmsMaterialContainer.BindStatus = CommonStatus.ENABLE;
                        await _wmsMaterialContainerRep.InsertNowAsync(addWmsMaterialContainer);
                        // 这里没有分拣操作直接更新库存信息
                        var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(u => u.ContainerCode == wmsMaterialContaine.ContainerCode);
                        wmsMaterialStock.PlaceCode = "N/A";
                        wmsMaterialStock.StockNumber -= wmsMaterialContaine.BindQuantity;
                        await _wmsMaterialStockRep.UpdateAsync(wmsMaterialStock);
                    }

                    string taskNo = "CHUKU" + DateTime.Today.ToString("yyyyMMdd");
                    var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
                    if (wmsTaskModel == null)
                    {
                        taskNo = taskNo + "0001";
                    }
                    else
                    {
                        //获取流水号最大的数据
                        var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
                        taskNo = SysCommUtil.GenerateNewInvoiceNumber(maxSerialNumber, 1);
                    }
                    // 新增任务
                    var addWmsTask = new WmsTask()
                    {
                        TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
                        TaskModel = TaskModel.SHOUDONG,
                        TaskType = TaskType.CHUKU,
                        TaskLevel = 1,
                        TaskStatus = TaskStatusEnum.WANCHENG,
                        ContainerCode = wmsContainer.ContainerCode,
                        SourcePlace = wmsPlace.PlaceCode,
                        Aisle = wmsPlace.Aisle,
                        ToPlace = "出库口",
                        AreaName = wmsArea.AreaName,
                        Description = wmsPlace.EmptyContainer == YesOrNot.Y ? "空托" : "物料",
                        OrderNo = orderNo,
                        TaskDodeviceStatus=TaskDodeviceStatusEnum.W,
                        UpdatedTime = DateTime.Now,
                    };
                    await _wmsTaskRep.InsertAsync(addWmsTask);

                    // 更新库位与周转箱号关系表状态为“删除”
                    wmsContainerPlace.ContainerPlaceStatus = CommonStatus.DELETED;
                    await _wmsContainerPlaceRep.UpdateAsync(wmsContainerPlace);

                    // 更新库位为“空闲”
                    wmsPlace.PlaceStatus = PlaceStatus.KONGXIAN;
                    wmsPlace.Islock = YesOrNot.N;
                    wmsPlace.EmptyContainer = YesOrNot.N;
                    await _wmsPlaceRep.UpdateAsync(wmsPlace);

                    // 更新周转箱号状态为“空闲”
                    wmsContainer.ContainerStatus = ContainerStatus.KOUXIAN;
                    await _wmsContainerRep.UpdateAsync(wmsContainer);
                }
            }
        }


        /// <summary>
        /// 呼叫空托
        /// </summary>
        /// <returns></returns>
        [HttpPost("callairflare")]
        [UnitOfWork]
        public async Task CallAirflare(CallAirflareInput input)
        {
            //获取库位中存货是空托的库位
            var wmsPlace = await _wmsPlaceRep.Where(u => u.PlaceStatus == PlaceStatus.CUNHUO && u.EmptyContainer== YesOrNot.Y).ToListAsync();
            if (wmsPlace.Count > 0)
            { 
                
            }
        }
    }
}